package org.springframework.security.config.annotation.web.configurers;

import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler;
import org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

/**
 * @author Dillon
 * @date 2024/7/8
 * @slogan 致敬大师 致敬未来的你
 * @desc 抽象的身份认证过滤器，对登录认证进行过滤
 */
public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
		AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {

	/**
	 * 构造函数
	 */
	public FormLoginConfigurer() {
		// 默认使用 UsernamePasswordAuthenticationFilter 作为过滤器
		super(new UsernamePasswordAuthenticationFilter(), null);
		// 设置用户名密码key
		usernameParameter("username");
		passwordParameter("password");
	}

	/**
	 * 默认登录页面路径
	 *
	 * @param loginPage 登录页面路径
	 * @return 当前配置对象
	 */
	@Override
	public FormLoginConfigurer<H> loginPage(String loginPage) {
		return super.loginPage(loginPage);
	}

	/**
	 * 设置username Key
	 *
	 * @param usernameParameter key
	 * @return 当前配置对象
	 */
	public FormLoginConfigurer<H> usernameParameter(String usernameParameter) {
		getAuthenticationFilter().setUsernameParameter(usernameParameter);
		return this;
	}

	/**
	 * 设置password Key
	 *
	 * @param passwordParameter key
	 * @return 当前配置对象
	 */
	public FormLoginConfigurer<H> passwordParameter(String passwordParameter) {
		getAuthenticationFilter().setPasswordParameter(passwordParameter);
		return this;
	}

	/**
	 * 鉴权失败后转发的失败url
	 *
	 * @param forwardUrl 失败url
	 * @return 当前配置对象
	 */
	public FormLoginConfigurer<H> failureForwardUrl(String forwardUrl) {
		failureHandler(new ForwardAuthenticationFailureHandler(forwardUrl));
		return this;
	}

	/**
	 * 鉴权成功后转发的失败url
	 *
	 * @param forwardUrl 失败url
	 * @return 当前配置对象
	 */
	public FormLoginConfigurer<H> successForwardUrl(String forwardUrl) {
		successHandler(new ForwardAuthenticationSuccessHandler(forwardUrl));
		return this;
	}

	/**
	 * 模板方法，执行初始化逻辑
	 *
	 * @param http 构建对象
	 * @throws Exception 执行异常
	 */
	@Override
	public void init(H http) throws Exception {
		super.init(http);
		initDefaultLoginFilter(http);
	}

	/**
	 * 设置处理登录URL
	 *
	 * @param loginProcessingUrl 登录URL
	 * @return 请求匹配器
	 */
	@Override
	protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
		return new AntPathRequestMatcher(loginProcessingUrl, "POST");
	}

	/**
	 * 获取设置的用户名 key
	 *
	 * @return key
	 */
	private String getUsernameParameter() {
		return getAuthenticationFilter().getUsernameParameter();
	}

	/**
	 * 获取设置的密码 key
	 *
	 * @return key
	 */
	private String getPasswordParameter() {
		return getAuthenticationFilter().getPasswordParameter();
	}

	/**
	 * 如果没有配置自定义的登录页面
	 * 则初始化默认的登录页面
	 *
	 * @param http httpSecurity
	 */
	private void initDefaultLoginFilter(H http) {
		DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
		if (loginPageGeneratingFilter != null && !isCustomLoginPage()) {
			loginPageGeneratingFilter.setFormLoginEnabled(true);
			loginPageGeneratingFilter.setUsernameParameter(getUsernameParameter());
			loginPageGeneratingFilter.setPasswordParameter(getPasswordParameter());
			loginPageGeneratingFilter.setLoginPageUrl(getLoginPage());
			loginPageGeneratingFilter.setFailureUrl(getFailureUrl());
			loginPageGeneratingFilter.setAuthenticationUrl(getLoginProcessingUrl());
		}
	}

}
